#ifndef SPL_MACROS
#define SPL_MACROS

#ifdef _WIN64
#define ARCHITECTURE "amd64"
#else
#define ARCHITECTURE "x86"
#endif

#define WIN32MANIFEST(architecture) \
    "/manifestdependency:\"type='win32' " ## \
    "name='Microsoft.Windows.Common-Controls' version='6.0.0.0' " ## \
    "processorArchitecture='" ## architecture ## "' " ## \
    "publicKeyToken='6595b64144ccf1df' " ## \
    "language='*'\""

#ifndef SPL_VISUAL_STYLES
#pragma comment(linker, WIN32MANIFEST(ARCHITECTURE))
#endif

#ifndef DEBUG_OUTPUT
#if defined(DEBUG) || defined(_DEBUG)

#define DEBUG_OUTPUT(x) OutputDebugString(x)

#else

#define DEBUG_OUTPUT(x)

#endif
#endif

#ifndef ASSERT
#if defined(DEBUG) || defined(_DEBUG)

#if (ASSERT_MODE == 0)
#define ASSERT(x) if (!(x)) DebugBreak();
#elif (ASSERT_MODE == 1)
#define ASSERT(x) if (!(x)) DEBUG_OUTPUT(_T("ASSERT FAILED: " ## _T(#x)));
#elif (ASSERT_MODE == 2)
#define ASSERT(x) if (!(x)) MessageBox(NULL, _T("ASSERT FAILED: " ## _T(#x)), NULL, MB_ICONERROR);
#endif

#else

#define ASSERT(x)

#endif
#endif

#define RECTWIDTH(rect) (rect.right - rect.left)
#define RECTHEIGHT(rect) (rect.bottom - rect.top)
#define RELATIVERECT(rect) \
    rect.right -= rect.left; \
    rect.bottom -= rect.top; \
    rect.left = rect.top = 0;

#define Menu_GetItemText(menu, id, buffer) { \
    MENUITEMINFO info; \
    info.cbSize     = sizeof(info); \
    info.fMask      = MIIM_STRING; \
    info.dwTypeData = buffer; \
    info.cch        = ARRAYSIZE(buffer); \
    buffer[0] = '\0'; \
    GetMenuItemInfo(menu, id, FALSE, &info); }

DLLEXPORT SPLINL void Error(const PTCHAR msg)
{
    MessageBox(NULL, msg, TEXT("Error"), MB_ICONERROR);
}
DLLEXPORT SPLINL void Error(const PTCHAR msg, const PTCHAR desc)
{
    const size_t len = _tcslen(msg) + _tcslen(desc) + 1;
    PTCHAR message = reinterpret_cast<PTCHAR>(malloc(len));

    _tcscpy_s(message, len, msg);
    _tcscat_s(message, len, desc);
    Error(message);
    free(message);
}

DLLEXPORT SPLINL HANDLE StringToHandle(LPCSTR szText, int nTextLen)
{
    if (nTextLen < 0)
        nTextLen = (int)strlen(szText) + 1;

    void *pszText = GlobalAlloc(GMEM_FIXED, nTextLen);

    memcpy(pszText, szText, nTextLen);
    return pszText;
}

/*template<typename POINTER>
struct Pointer {
protected:
    POINTER ptr;

public:
    SPLINL operator POINTER() { return ptr; }
    SPLINL Pointer(POINTER ptr) { this->ptr = ptr; }
    SPLINL ~Pointer() { delete ptr; }
};

template<typename POINTER>
struct PointerArray {
protected:
    POINTER ptr;

public:
    SPLINL operator POINTER() { return ptr; }
    SPLINL PointerArray(POINTER ptr) { this->ptr = ptr; }
    SPLINL ~PointerArray() { delete[] ptr; }
};

struct String : PointerArray<PTCHAR> {
public:
    SPLINL PTCHAR   copy(PTCHAR dest)   { return _tcscpy(dest, ptr); }
    SPLINL PTCHAR   append(PTCHAR text) { return _tcscat(ptr, text); }
    SPLINL size_t   length()            { return _tcslen(ptr); }

    SPLINL String(PTCHAR text) : PointerArray(text) {}
};*/

#endif